package org.scau.studentevaluation.config;

import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import org.scau.studentevaluation.entity.response.Result;
import org.scau.studentevaluation.enums.ResponseCodeEnum;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName: FeignResultDecoder
 * @Description: TODO feign解码器，只实现了自动拆箱
 * 0、需要注意的是，这样是一定会把result拆出来，所以每个接收的值都必须是被包装的
 * 1、可以正常拆出string类型
 * 2、可以拆出pojo，但目前里面的jdk8的时间类拆不了
 * 3、时间类的bug已搞定，跟之前的jsonutils有关
 * 4、已实现可以接收A<B,C,D....>， 但是需要接口处需要指定具体类型，因为如果用list的话无法实例化，用ArrayList、linkedlist等才满足实际需求。这样做的原因是不想默认用ArrayList或者hashmap接收。
 * @Author: sunslikes
 * @Date: 2020/9/4 23:07
 * @Version: 1.0
 */
public class FeignResultDecoder implements Decoder {

    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        // 这里的type居然是真实类型，牛逼
        if (type instanceof Class) {
            String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
            Result result = JsonUtils.json2GenricObj(bodyStr, Result.class, (Class)type);
            if (result.getCode() != ResponseCodeEnum.SUCCESS.getType()) {
                // 统一错误处理，暂时就不处理了，不知道大家里面怎么样会导致错误代码
            }
            return result.getData();
        } else if (type instanceof ParameterizedType
                || type instanceof WildcardType) {
            // ParameterizedType 泛型类型
            // 下面可以分为接受List或者Map
            String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
            ParameterizedType parameterizedType = (ParameterizedType) type;
            // 想了想如果我每次list和map都用ArrayList和hashmap接收那不是笨笨，一点都不现实，还是接受的时候声明list类具体型好
            Class rawClass = (Class) parameterizedType.getRawType();
            Type[] innerTypes = parameterizedType.getActualTypeArguments();
            Class[] innerClasses = Stream.of(innerTypes).map(bType -> (Class) bType).collect(Collectors.toList()).toArray(new Class[0]);
            Result result = JsonUtils.json2GenricGenricObj(bodyStr, Result.class, rawClass, innerClasses);
            if (result.getCode() != ResponseCodeEnum.SUCCESS.getType()) {
                // 统一错误处理，暂时就不处理了，不知道大家里面怎么样会导致错误代码
            }
            return result.getData();
        }
        throw new DecodeException(
                "type is not an instance of Class or ParameterizedType: " + type);

    }
}
